package com.hp.bon.sgw.util;

import java.util.List;
import java.util.regex.Pattern;

import org.dom4j.Element;
import org.dom4j.Node;

import com.hp.bon.sgw.Constants;

public class XmlValidatorDef {
	public String capability;
	public boolean enabled = true;
	public List<XmlValidatorRule> validatorRules;

	public int validateXML(Element el, StringBuilder hint) {
		final int SUCCESS = 0;
		if (!enabled) {
			return SUCCESS;
		}
		for (XmlValidatorRule rule : validatorRules) {
			Object selected = null;
			if (rule.required) {
				selected = el.selectSingleNode(rule.xpath);
				if (selected == null) {
					hint.append("failed,can't find required node ,failed rule :"
							+ rule.name);
					if (rule.errCode != 0) {
						return rule.errCode;
					} else {
						return Constants.ResultCode.MISSING_TAG;
					}
				}
			} else {
				selected = el.selectObject(rule.xpath);
			}
			if (selected == null) {
				hint.append("failed,can't find node ,failed rule :" + rule.name);
				if (rule.errCode != 0) {
					return rule.errCode;
				} else {
					return Constants.ResultCode.MISSING_TAG;
				}
			}
			if (selected instanceof Node) {
				String value = ((Node) selected).getStringValue();
				if (!matchValue(value, rule, hint)) {
					if (rule.errCode != 0) {
						return rule.errCode;
					} else {
						return Constants.ResultCode.VALUE_ERROR;
					}
				}
			} else if (selected instanceof List) {
				List<?> nodes = (List<?>) selected;
				if (!nodes.isEmpty()) {
					String value = Integer.toString(nodes.size());
					if (!matchValue(value, rule, hint)) {
						if (rule.errCode != 0) {
							return rule.errCode;
						} else {
							return Constants.ResultCode.VALUE_ERROR;
						}
					}
				}
			} else {
				hint.append("failed,failed rule :")
						.append(rule.name)
						.append(" not valid rule ,selected class name "
								+ selected.getClass().getName());
				if (rule.errCode != 0) {
					return rule.errCode;
				} else {
					return Constants.ResultCode.VALUE_ERROR;
				}
			}

		}
		return SUCCESS;
	}

	private boolean matchValue(String value, XmlValidatorRule rule,
			StringBuilder hint) {
		boolean matched = Pattern.matches(rule.checker, value);
		if (!matched) {
			hint.append("failed,failed rule :").append(rule.name)
					.append(" cur:").append(value)
					.append(" expected:" + rule.checker);
			return false;
		} else {
			return true;
		}

	}
}
